from zope.interface import implements
from twisted.internet import interfaces, reactor, protocol
from twisted.internet.protocol import ServerFactory, Factory, ClientFactory, ReconnectingClientFactory
from twisted.protocols import basic
from twisted.internet.protocol import Protocol
import Tkinter
from PIL import Image, ImageTk
import StringIO
import os, sys
from time import time
import cStringIO
import wx
import ImageUtil
from nodeinfo import Info

root = Tkinter.Tk()
root.geometry('+%d+%d' % (300,300))
selfinfo = Info()

class ContentProducer:
  implements(interfaces.IPushProducer)
  
  def __init__(self, protocol):
    self.protocol = protocol
    self.imgData = []
    self.path = 'E:\\pyClients\\'+selfinfo.getName()+'\\a.jpg'
    self.im = Image.open(self.path, 'r')
    self.startTime = None
    self.ddataRate = 0.0
    self.lineCount = 0
    
  def pauseProducing(self):
    #print "ContentProducer paused"
     pass
    
  def resumeProducing(self):
    # get the image as a string data in array self.imgData
    self.imgData = ImageUtil.getImageDataInArray(self, str(self.im.tostring()))
    imLen = len(self.imgData)
    for i in range(0, imLen):
        # send the string image data to the client.
        self.protocol.transport.write(str(self.imgData[i])+"\r\n")
        self.lineCount += 1
        # if self.lineCount % 1000 == 0:
        if not self.startTime:
            self.startTime = time()
        if self.lineCount == 1000:
            print "rate = %.2f lines / second" % (self.lineCount / (time()-self.startTime))
            self.ddataRate = str((self.lineCount / (time()-self.startTime)))
            self.lineCount = 0
            self.startTime = time()

        
  def stopProducing(self):
    pass

class NodeLineProtocol(basic.LineReceiver):
  def __init__(self):
    self.lineCount = 0
    self.rate = 0.0
    self.startTime = time()
    self.imageData = ''
      
  def connectionMade(self):
    if self.factory.name == 'Server':
      self.producer = ContentProducer(self)
      self.transport.registerProducer(self.producer, True)
      self.producer.resumeProducing()
    elif self.factory.name == 'Client':
      self.transport.write('connectserver='+ selfinfo.getName() +' '+ str(selfinfo.getListenPort())+'\r\n')
      print 'Information sent to server:' + selfinfo.getName() +' '+ str(selfinfo.getListenPort())
      
  def connectionLost(self, connector):
    pass
    
  def lineReceived(self, data):
    if data.startswith('data='):
        self.imageData = ImageUtil.getImageInString(self, data)
        if 'end of data' in data:
            saveNDisplayImage(self.imageData)
            self.imageData = ''
        elif data.startswith('servererrmsg='):
            print data[13:]
        
    #print str(len(line))
    #img = Image.fromstring('RGB', (293, 220), line)
    """file = 'ttt'
    img.save(file + ".thumbnail", "JPEG")
    imageOpen = Image.open(file, 'r')
    """

"""""""""""""""""""""""""""""""""""""""""""""""""""
TKinter app to display image in a Label
"""""""""""""""""""""""""""""""""""""""""""""""""""
def saveNDisplayImage(im):
    img = Image.fromstring('RGB', (293, 220), im)
    #path to save the received image
    file = 'E:\\pyClients\\'+ selfinfo.getName()+'\\clip'
    #save the image as a thumbnail
    img.save(file + ".thumbnail", "JPEG")
    #change the image to Tkinter image
    tk_im = ImageTk.PhotoImage(img)
    #display the image in a label
    label_val = Tkinter.Label(root, image = tk_im)
    label_val.place(x=0,y=0,width=200,height=200)
    root.after(2, root.quit)
    root.mainloop(0)

#This class is the server for the node
class NodeServerFactory(Factory):
  protocol = NodeLineProtocol
  isServer = True
  def __init__(self, name):
    self.name = name

# This class is the client for the node
class NodeClientFactory(ClientFactory):  
  protocol = NodeLineProtocol
  isServer = False
  def __init__(self, name):
    self.name = name

# It establishes connection with the server and listens to the clients
def establishConnection(serverFactory, clientFactory):
    selfinfo.setName(str(sys.argv[2]))
    selfinfo.setListenPort(int(sys.argv[1]))
    reactor.connectTCP("localhost", 2000, clientFactory)
    reactor.listenTCP(int(sys.argv[1]), serverFactory)
    # path for saving the image data received from server
    path = 'E:\\pyClients\\'+selfinfo.getName()
    if not os.path.exists(path):
        os.makedirs(path)
    reactor.run()

#Main method of the class    
if __name__ == '__main__':
    serverFactory = NodeServerFactory("Server")
    clientFactory = NodeClientFactory("Client")
    if len(sys.argv) == 3:
        establishConnection(serverFactory, clientFactory)
    else:
        print('Enter the following values <filename><name><port>')